home *** CD-ROM | disk | FTP | other *** search
- ;* METHODS.S
- ;************************************************************************
- ;* *
- ;* PC Scheme/Geneva 4.00 Scheme code *
- ;* *
- ;* (c) 1985-1988 by Texas Instruments, Inc. See COPYRIGHT.TXT *
- ;* (c) 1992 by L. Bartholdi & M. Vuilleumier, University of Geneva *
- ;* *
- ;*----------------------------------------------------------------------*
- ;* *
- ;* Scoops: Addition Redefinition and Deletion of Methods *
- ;* *
- ;*----------------------------------------------------------------------*
- ;* *
- ;* Created by: Amitabh Srivastava Date: 1986 *
- ;* Revision history: *
- ;* - 18 Jun 92: Renaissance (Borland Compilers, ...) *
- ;* *
- ;* ``In nomine omnipotentii dei'' *
- ;************************************************************************
-
- ; is class1 before class2 in class ?
- ; class1 is not equal to class2
-
- (define %before
- (lambda (class1 class2 class)
- (or (eq? class1 class)
- (memq class2 (memq class1 (%sc-mixins (%sc-name->class class)))))))
-
- ;
-
- (macro define-method
- (lambda (e)
- (let ((class-name (caadr e))
- (method-name (cadr (cadr e)))
- (formal-list (caddr e))
- (body (cdddr e)))
- `(%SC-CLASS-ADD-METHOD
- ',class-name
- ',method-name
- ',class-name
- ',class-name
- ,(%sc-expand
- `(LAMBDA ,formal-list
- (LET ((SELF (FLUID SELF)))
- ,@body)))
- (LAMBDA (ENV VAL)
- (SET! (ACCESS ,method-name ENV) VAL))))))
-
-
- ;
-
- (define %sc-class-add-method
- (lambda (class-name method-name method-class mixin-class method assigner)
- (let ((class (%sc-name->class class-name)))
- (apply-if (assq method-name (%sc-method-values class))
- (lambda (entry)
- (set-cdr! entry method))
- (%sc-set-method-values class
- (cons (cons method-name method) (%sc-method-values class)))))
- (%compiled-add-method class-name method-name method-class mixin-class
- method assigner)))
-
-
- ;
-
- (define %inform-subclasses
- (lambda (class-name method-name method-class mixin-class method assigner)
- ((rec loop
- (lambda (class-name method-name method-class mixin-class
- method assigner subclass)
- (if subclass
- (begin
- (%compiled-add-method
- (car subclass) method-name method-class class-name
- method assigner)
- (loop class-name method-name method-class mixin-class
- method assigner
- (cdr subclass))))))
- class-name method-name method-class mixin-class method assigner
- (%sc-subclasses (%sc-name->class class-name)))))
-
-
- ;
-
- (define %compiled-add-method
- (lambda (class-name method-name method-class mixin-class method assigner)
- (letrec
- ((class (%sc-name->class class-name))
-
- (insert-entry
- (lambda (previous current)
- (cond ((null? current)
- (set-cdr! previous
- (cons (cons method-class mixin-class) '())))
- ((eq? mixin-class (cdar current))
- (set-car! (car current) method-class))
- ((%before mixin-class (cdar current)
- class-name)
- (set-cdr! previous
- (cons (cons method-class mixin-class) current)))
- (else '()))))
-
-
- (loop-insert
- (lambda (previous current)
- (if (not (insert-entry previous current))
- (loop-insert (current) (cdr current)))))
-
- (insert
- (lambda (entry)
- (if (insert-entry entry (cdr entry)) ;;; insert at head
- (add-to-environment)
- (loop-insert (cdr entry) (cddr entry)))))
-
- (add-to-environment
- (lambda ()
- (if (%sc-class-compiled class)
- (assigner (%sc-method-env class) method))
- (if (%sc-subclasses class)
- (%inform-subclasses class-name method-name method-class
- mixin-class method assigner))))
-
- (add-entry
- (lambda ()
- (%sc-set-method-structure class
- (cons (list method-name (cons method-class mixin-class))
- (%sc-method-structure class)))
- (add-to-environment)))
- )
-
- (let ((method-entry (assq method-name (%sc-method-structure class))))
- (if method-entry
- (insert method-entry)
- (add-entry))
- method-name))))
-
- ;
-
- (macro delete-method
- (lambda (e)
- (let ((class-name (caadr e))
- (method-name (cadr (cadr e))))
- `(%SC-CLASS-DEL-METHOD
- ',class-name
- ',method-name
- ',class-name
- ',class-name
- (LAMBDA (ENV VAL)
- (SET! (ACCESS ,method-name ENV) VAL))
- #F))))
-
- ;
-
- (define %deleted-method
- (lambda (name)
- (lambda args
- (error-handler name 3 #T))))
-
-
- ;
-
- (define %sc-class-del-method
- (lambda (class-name method-name method-class mixin-class assigner del-value)
- (let ((class (%sc-name->class class-name)))
- (apply-if (assq method-name (%sc-method-values class))
- (lambda (entry)
- (%sc-set-method-values class
- (delq! entry (%sc-method-values class)))
- (%compiled-del-method class-name method-name method-class mixin-class
- assigner del-value))
-
- (error-handler method-name 4 #T)))))
-
-
- ;
-
- (define %inform-del-subclasses
- (lambda (class-name method-name method-class mixin-class assigner del-value)
- ((rec loop
- (lambda (class-name method-name method-class mixin-class assigner
- del-value subclass)
- (if subclass
- (begin
- (%compiled-del-method (car subclass) method-name
- method-class class-name assigner del-value)
- (loop class-name method-name method-class mixin-class assigner
- del-value (cdr subclass))))))
- class-name method-name method-class mixin-class assigner del-value
- (%sc-subclasses (%sc-name->class class-name)))))
-
-
- ;
-
- (define %compiled-del-method
- (lambda (class-name method-name method-class mixin-class assigner del-value)
- (let ((class (%sc-name->class class-name)))
- (letrec
- ((delete-entry
- (lambda (previous current)
- (cond ((eq? mixin-class (cdar current))
- (set-cdr! previous (cdr current)) #T)
- (else #F))))
-
- (loop-delete
- (lambda (previous current)
- (cond ((or (null? current)
- (%before mixin-class (cdar previous)
- class-name))
- (error-handler method-name 4 #T))
- ((delete-entry previous current) #T)
- (else (loop-delete current (cdr current))))))
-
- (delete
- (lambda (entry)
- (if (delete-entry entry (cdr entry)) ;;; delete at head
- (modify-environment entry)
- (loop-delete (cdr entry) (cddr entry)))))
-
- (modify-environment
- (lambda (entry)
- (cond ((null? (cdr entry))
- (%sc-set-method-structure class
- (delq! (assq method-name (%sc-method-structure class))
- (%sc-method-structure class)))
- (if (%sc-class-compiled class)
- (assigner (%sc-method-env class)
- (or del-value
- (set! del-value
- (%deleted-method method-name)))))
- (if (%sc-subclasses class)
- (%inform-del-subclasses class-name method-name
- method-class mixin-class assigner del-value)))
- (else
- (let ((meth-value
- (%sc-get-meth-value method-name
- (%sc-name->class (caadr entry)))))
- (if (%sc-class-compiled class)
- (assigner (%sc-method-env class) meth-value))
- (if (%sc-subclasses class)
- (%inform-subclasses class-name
- method-name
- method-class
- mixin-class
- meth-value assigner)))))))
- )
-
- (let ((method-entry (assq method-name (%sc-method-structure class))))
- (if method-entry
- (delete method-entry)
- (error-handler method-name 4 #T))
- method-name)))))